/************************************************************
* @file   gkt_timer.h
************************************************************/

#ifndef GKT_TIMER_H
#define GKT_TIMER_H

#include "gkt_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/* timer type */
enum {
	GKT_TIMER_TYPE_BASE = 0,
	GKT_TIMER_TYPE_TCCR,
	GKT_TIMER_TYPE_ADV,
	GKT_TIMER_TYPE_MAX
};

/* timer mode */
enum {
	GKT_TIMER_MODE_TIMER = 0,
	GKT_TIMER_MODE_PWM,
	GKT_TIMER_MODE_MAX
};

typedef void (*gkt_timer_callback)(gkt_handle_t handle);

typedef struct _gkt_base_timer_cfg_attr {
	int	mode;	/* 0: timer, 1: pwm */

	union {
		struct {
			uint32_t	interval;	/* unit in us */
			int	auto_reload;
			gkt_timer_callback	callback;
		} timer;
		struct {
			uint32_t	frequence;	/* HZ */
			uint32_t	duty_cycle;	/* [0, 100], 0%: 0, 50%: 50, 100%: 100 */
			int	start_level;
		} pwm;
	};
} gkt_base_timer_cfg_attr_s;

#define GKT_TCCR_USED_NUM3		3
#define GKT_TCCR_USED_NUM2		2
#define GKT_TCCR_USED_NUM1		1
#define GKT_TCCR_USED_NUM0		0


typedef int (*gkt_tccr_capture_callback)(uint32_t cap0_val, uint32_t cap_num, uint32_t cap_num_val);

/*time tccr function*/
typedef enum {
	GKT_TIMER_NORMAL,						/*Normal timer, use of counting clock*/
	GKT_TIMER_COMPARE_PULSE_SIGNAL_OUTPUT,
	GKT_TIMER_CAPTURE_MEASURE_PULSE_WIDTH,/* capture0 must be involved,others are optional */	
	GKT_TIMER_FUNCTION_MAX
}gkt_timer_tccr_function_e;

typedef enum {
	GKT_TIMER_CAPTURE_COM1 = 1,
	GKT_TIMER_CAPTURE_COM2 = 2,
	GKT_TIMER_CAPTURE_COM3 = 4,
} gkt_timer_tccr_capture_compose_e;

typedef enum
{
	GKT_TIMER_TCCR_EXRELOAD_DISABLED,
	GKT_TIMER_TCCR_EXRELOAD_ENABLED,
}gkt_timer_tccr_external_reload_e;

typedef struct _gkt_tccr_timer_counter_attr {
	uint32_t					reload_value;	/*capture must set 0*/
	gkt_timer_callback			counter_notify;
} gkt_tccr_timer_counter_attr_s;

typedef struct _gkt_tccr_timer_comp_attr {
	uint32_t					reload_value;	/*capture must set 0*/
	uint32_t					used_num;		/*0~3 compare number can be used*/
	uint32_t					compare_value;	/*compare value must be greater than reload value*/
	gkt_timer_callback			compare_notify;
} gkt_tccr_timer_comp_attr_s;

/*capture plus wide attr*/
typedef struct _gkt_tccr_timer_cap_attr {
	uint32_t					ex_reload;			/*external reload 0:disabled, 1:enabled*/
	uint32_t					cc0_int_act;		/*0:capture0 rise edge, 1:capture0 falling edge*/
	uint8_t						used_com;
	gkt_tccr_capture_callback	capture_callback;	/*output capture value*/
} gkt_tccr_timer_cap_attr_s;

/*Only affect Capture 0:*/
typedef enum
{
	GKT_TIMER_TCCR_CAPTURE_FALLING_EDGE,
	GKT_TIMER_TCCR_CAPTURE_RISE_EDGE
}gkt_timer_tccr_capture_int_action_e;


typedef enum {
	GKT_TIMER_TCCR_DISABLED,
	GKT_TIMER_TCCR_SOFTWARE,
	GKT_TIMER_TCCR_RELOAD_AUTO,			/*overflow auto reload----compare and counter used*/
	GKT_TIMER_TCCR_FALLINGEDGE_RELOAD,	/*reload on the falling edge of tccr_ex--capture used*/
	GKT_TIMER_TCCR_MODE_MAX
}gkt_timer_tccr_reload_mode_e;

typedef struct _gkt_tccr_timer_cfg_attr {
	gkt_timer_tccr_function_e			function;
	gkt_timer_tccr_reload_mode_e		reload_mode; 	/*compare set 3:auto, capture set 4:reload*/
	union {
		gkt_tccr_timer_counter_attr_s 	counter_attr;
		gkt_tccr_timer_comp_attr_s 		compare_attr;
		gkt_tccr_timer_cap_attr_s		cap_plus_wide_attr;
	};
} gkt_tccr_timer_cfg_attr_s;

gkt_handle_t gkt_timer_open(uint32_t type, 
					uint32_t dev_id, uint32_t channel_id);

int gkt_timer_config(gkt_handle_t handle, void *attr);

int gkt_timer_start(gkt_handle_t handle);

int gkt_timer_stop(gkt_handle_t handle);

void gkt_timer_close(gkt_handle_t handle);

int gkt_timer_init(void);

int gkt_timer_set_pwm_period(gkt_handle_t handle, uint32_t pwm_cnt);

#ifdef __cplusplus
}
#endif

#endif	/* GKT_TIMER_H */


